package com.cqndt.disaster.device.sys.controller;

import com.cqndt.disaster.device.common.annotation.SysLog;
import com.cqndt.disaster.device.sys.service.SysUserService;
import com.cqndt.disaster.device.sys.shiro.ShiroUtils;
import com.cqndt.disaster.device.sys.vo.SysUserVo;
import com.cqndt.disaster.device.util.AbstractController;
import com.cqndt.disaster.device.util.Constant;
import com.cqndt.disaster.device.util.RASUtils;
import com.cqndt.disaster.device.util.Result;
import com.google.code.kaptcha.Constants;
import com.google.code.kaptcha.Producer;
import org.apache.shiro.authc.*;
import org.apache.shiro.subject.Subject;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.security.KeyPair;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created By marc
 * Date: 2019/3/6  14:21
 * Description:登录
 */
@RestController
public class SysLoginController extends AbstractController {
    @Autowired
    private Producer producer;
    @Autowired
    private SysUserService sysUserService;

    /**
     * 获取验证码
     *
     * @param response
     * @throws IOException
     */
    @GetMapping("getCaptcha")
    public void captcha(HttpServletResponse response) throws IOException {
        response.setHeader("Cache-Control", "no-store, no-cache");
        response.setContentType("image/jpeg");
        //生成文字验证码
        String text = producer.createText();
        //生成图片验证码
        BufferedImage image = producer.createImage(text);
        //保存到shiro session
        ShiroUtils.setSessionAttribute(Constants.KAPTCHA_SESSION_KEY, text);
        ServletOutputStream out = response.getOutputStream();
        ImageIO.write(image, "jpg", out);
    }

    /**
     * 验证验证码
     *
     * @param code
     * @throws IOException
     */
    @GetMapping("checkCaptcha")
    public Result checkCaptcha(String code) {
        try {
            String kaptcha = ShiroUtils.getKaptcha(Constants.KAPTCHA_SESSION_KEY);
            if(!kaptcha.equalsIgnoreCase(code)){
                return new Result().failure(-1,"验证码错误");
            }
        } catch (Exception e) {
            return new Result().failure(-1, e.getMessage());
        }
        return new Result().success();
    }

    /**
     * 登录
     */
    @SysLog("登录")
    @PostMapping("login")
    public Result login(String userName, String password) {
        Result result = new Result();
        try {
            //将前端密码解密
            Object privateKey = ShiroUtils.getSession().getAttribute(Constant.PRIVATE_KEY);
            if (privateKey == null) {
                return new Result().failure(404, "请刷新后重新登陆");
            }
            //私钥解密(私钥对象，私钥加密串)。私钥加密串转byte,不是解密不成功或者报input too large for RSA cipher或Bad arguments
            byte[] passwords = RASUtils.decrypt((RSAPrivateKey) privateKey, RASUtils.hexStringToBytes(password));
            //还原密码
            password = new String(passwords).trim();
            Subject subject = ShiroUtils.getSubject();
            UsernamePasswordToken token = new UsernamePasswordToken(userName, password);
            subject.login(token);
            SysUserVo vo = ShiroUtils.getUserEntity();
            if((vo.getAduitType()&1) == 0){
                return new Result().failure(404,"该用户没有访问权限");
            }
            //查询当前用户的权限
            List<String> permsList = sysUserService.queryPermsForUser(getUserId());
            String areaId = sysUserService.getAreaIdByUserId(getUserId());
            Map<String, Object> map = new HashMap<>();
            map.put("permsList", permsList);
            map.put("user", vo);
            map.put("userName", userName);
            map.put("areaId", areaId);
            result.setData(map);
            //保存到shiro session
            ShiroUtils.setSessionAttribute(Constant.USER_NAME, userName);
            //session验证码和秘钥移除
            ShiroUtils.getSession().removeAttribute(Constants.KAPTCHA_SESSION_KEY);
            ShiroUtils.getSession().removeAttribute(Constant.PRIVATE_KEY);
        } catch (UnknownAccountException e) {
            return result.failure(-1, e.getMessage());
        } catch (IncorrectCredentialsException e) {
            return result.failure(-1, "账号或密码不正确");
        } catch (LockedAccountException e) {
            return result.failure(-1, "账号已被禁用,请联系管理员");
        } catch (AuthenticationException e) {
            return result.failure(-1, e.getMessage());
        } catch (Exception e) {
            return result.failure(-1, e.getMessage());
        }
        return result;
    }

    /**
     * 退出
     */
    @GetMapping("logout")
    public Result logout() {
        ShiroUtils.logout();
        return new Result().success();
    }

    @ApiOperation("获取公钥和私钥")
    @GetMapping("getKey")
    public Result getKey() {
        HashMap<Object, Object> hashMap = new HashMap<>();
        RSAPublicKey rsapPublicKey = null;
        RSAPrivateKey rsaPrivateKey = null;
        try {
            KeyPair publicKey = RASUtils.generateKeyPair();
            rsapPublicKey = (RSAPublicKey) publicKey.getPublic();
            rsaPrivateKey = (RSAPrivateKey) publicKey.getPrivate();
        } catch (Exception e) {
            e.printStackTrace();
        }
        //保存到shiro session
        ShiroUtils.setSessionAttribute(Constant.PRIVATE_KEY, rsaPrivateKey);
        hashMap.put("publicKey", rsapPublicKey.getModulus().toString(16));
        return new Result().success(hashMap);
    }

}
